'use strict';

const {
  CommonDeletedEnum,
} = require("../utils/enum");
const Service = require('egg').Service;
function getNestedProperty(obj, path) {
  return path.split('.').reduce((current, key) => {
    return current && current[key] !== undefined ? current[key] : undefined;
  }, obj);
}
class BaseService extends Service {
  constructor(ctx) {
    super(ctx);
    // 如果子类没有通过 getter 定义 model，则尝试通过 modelName 获取
    if (!this.model) {
      const modelName = this.constructor.modelName;
      if (!modelName) {
        throw new Error('Model must be specified either through getter or static modelName in child class');
      }
      this.model = getNestedProperty(ctx.model, modelName);
    }
  }
  // 允许子类通过 getter 重写 model
  get model() {
    return this._model;
  }

  set model(val) {
    this._model = val;
  }

  async beforeCreate() {
    return true
  }

  async beforeUpdate() {
    return true
  }

  /**
   * Create a new record
   * @param {Object} payload
   */
  async create(payload) {
    await this.beforeCreate(payload);
    return this.model.create({
      ...payload,
      create_time: new Date()
    });
  }

  /**
   * Find record by id
   * @param {String|Number} id
   */
  async findById(id) {
    return this.model.findOne({
      where: {
        id,
        deleted: CommonDeletedEnum.NOT_DELETED
      },
      include: this.getDetailInclude()
    });
  }

  /**
   * Update record
   * @param {String|Number} id
   * @param {Object} payload
   */
  async update(id, payload) {
    const model = await this.findById(id);
    if (!model) {
      this.ctx.throw(500, 'ID不存在');
    }
    await this.beforeUpdate(id, payload);
    return model.update(payload);
  }

  /**
   * Soft delete record
   * @param {String|Number} id
   * @param {String|Number} userId
   */
  async delete(id, userId = 0) {
    const model = await this.model.findOne({
      where: {
        id
      }
    })
    if (!model) {
      throw new Error('删除对象不存在')
    }
    // return model.update({
    //   deleted: CommonDeletedEnum.DELETED,
    //   updater: userId || 0,
    //   update_time: new Date()
    // });
    return this.model.destroy({
      where: {
        id,
      },
    })
  }

  /**
   * List records with pagination
   * @param {Object} query Query conditions
   * @param {Object} options Pagination options
   * @param {Array} order Sort order, default is [['create_time', 'DESC']]
   * @param {Object} include Include associations
   */
  async page(query, options, order = [['create_time', 'DESC']]) {
    const { page, pageSize } = options;
    const where = {
      ...query,
      deleted: CommonDeletedEnum.NOT_DELETED,
      ...this.setAfterPageQuery()
    };
    const findOptions = {
      where,
      offset: (page - 1) * pageSize,
      limit: pageSize,
      order,
      distinct: true
    };
    findOptions.include = this.getPageInclude()
    if (this.getPageOrder()) {
      findOptions.order = this.getPageOrder()
    }
    const { count, rows } = await this.model.findAndCountAll(findOptions);
    return {
      list: rows,
      total: count,
      current: page,
      pageSize,
      totalPages: Math.ceil(count / pageSize),
    };
  }
  /**
   * 获取列表（不分页）
   * @param {Object} query 查询条件
   * @param {Array} order 排序条件 默认按创建时间倒序
   */
  async list(query = {}, order = [['create_time', 'DESC']]) {
    const where = {
      ...query,
      deleted: CommonDeletedEnum.NOT_DELETED
    };

    const findOptions = {
      where,
      order
    };
    findOptions.include = this.getListInclude()
    if (this.getListOrder()) {
      findOptions.order = this.getListOrder()
    }
    console.log(findOptions)
    return await this.model.findAll(findOptions);
  }

  getPageInclude() {
    return []
  }
  getListInclude() {
    return []
  }
  getDetailInclude() {
    return []
  }

  getPageOrder() {
    return null
  }
  getListOrder() {
    return null
  }
  setAfterPageQuery() {
    return {}
  }
}

module.exports = BaseService;
